#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
发送案例构建请求的脚本

向指定的 API 端点发送 POST 请求，用于构建案例场景。

使用方法:
    python scripts/send_case_construction_request.py
    
    或者自定义参数:
    python scripts/send_case_construction_request.py \\
        --url http://133.133.134.61:5000/api/case_construction \\
        --scenario-id checkoutservice2-0_1652075078 \\
        --components checkoutservice node
"""

import argparse
import json
import sys
from typing import List, Dict, Any, Optional

try:
    import requests
except ImportError:
    print("错误: 未安装 requests 库")
    print("请运行: pip install requests")
    sys.exit(1)


def send_case_construction_request(
    url: str,
    scenario_id: str,
    components: List[str],
    timeout: int = 30,
    verbose: bool = False
) -> Dict[str, Any]:
    """
    发送案例构建请求到指定的 API 端点
    
    Args:
        url: API 端点 URL
        scenario_id: 场景 ID
        components: 组件列表
        timeout: 请求超时时间（秒），默认 30 秒
        verbose: 是否显示详细输出，默认 False
    
    Returns:
        包含响应数据的字典
    
    Raises:
        requests.exceptions.RequestException: 当请求失败时抛出异常
    """
    # 构建请求数据
    data = {
        "scenario_id": scenario_id,
        "components": components
    }
    
    if verbose:
        print(f"发送请求到: {url}")
        print(f"请求数据: {json.dumps(data, indent=2, ensure_ascii=False)}")
    
    try:
        # 发送 POST 请求
        response = requests.post(
            url,
            json=data,
            timeout=timeout,
            headers={"Content-Type": "application/json"}
        )
        
        # 检查 HTTP 状态码
        response.raise_for_status()
        
        # 解析响应 JSON
        result = response.json()
        
        if verbose:
            print(f"响应状态码: {response.status_code}")
            print(f"响应数据: {json.dumps(result, indent=2, ensure_ascii=False)}")
        
        return {
            "success": True,
            "status_code": response.status_code,
            "data": result
        }
        
    except requests.exceptions.Timeout:
        error_msg = f"请求超时（超过 {timeout} 秒）"
        if verbose:
            print(f"错误: {error_msg}")
        return {
            "success": False,
            "error": error_msg,
            "error_type": "Timeout"
        }
        
    except requests.exceptions.ConnectionError as e:
        error_msg = f"连接错误: {str(e)}"
        if verbose:
            print(f"错误: {error_msg}")
        return {
            "success": False,
            "error": error_msg,
            "error_type": "ConnectionError"
        }
        
    except requests.exceptions.HTTPError as e:
        error_msg = f"HTTP 错误: {e.response.status_code} - {str(e)}"
        if verbose:
            print(f"错误: {error_msg}")
        try:
            error_detail = e.response.json()
        except:
            error_detail = e.response.text
        return {
            "success": False,
            "error": error_msg,
            "error_type": "HTTPError",
            "status_code": e.response.status_code,
            "error_detail": error_detail
        }
        
    except requests.exceptions.RequestException as e:
        error_msg = f"请求异常: {str(e)}"
        if verbose:
            print(f"错误: {error_msg}")
        return {
            "success": False,
            "error": error_msg,
            "error_type": "RequestException"
        }
        
    except json.JSONDecodeError as e:
        error_msg = f"响应 JSON 解析失败: {str(e)}"
        if verbose:
            print(f"错误: {error_msg}")
            print(f"响应内容: {response.text[:500]}")
        return {
            "success": False,
            "error": error_msg,
            "error_type": "JSONDecodeError",
            "raw_response": response.text[:500] if 'response' in locals() else None
        }
        
    except Exception as e:
        error_msg = f"未知错误: {str(e)}"
        if verbose:
            print(f"错误: {error_msg}")
        return {
            "success": False,
            "error": error_msg,
            "error_type": "UnknownError"
        }


def batch_test_scenarios(
    samples_json_path: str,
    url: str,
    components: List[str],
    timeout: int = 30,
    verbose: bool = False
) -> Dict[str, Any]:
    """
    批量测试所有 test 场景的 API 请求
    
    Args:
        samples_json_path: samples.json 文件路径
        url: API 端点 URL
        components: 默认组件列表
        timeout: 请求超时时间（秒）
        verbose: 是否显示详细输出
    
    Returns:
        包含测试统计信息的字典
    """
    # 读取 samples.json
    try:
        with open(samples_json_path, 'r', encoding='utf-8') as f:
            samples_data = json.load(f)
    except Exception as e:
        print(f"❌ 读取 samples.json 失败: {e}")
        return {"error": str(e)}
    
    # 筛选出所有 dataset_type 为 "test" 的场景
    test_scenarios = [
        scenario for scenario in samples_data.get("scenarios", [])
        if scenario.get("dataset_type") == "test"
    ]
    
    print(f"📊 从 samples.json 中找到 {len(test_scenarios)} 个测试场景")
    print("=" * 80)
    
    # 统计变量
    success_count = 0
    failed_count = 0
    failed_scenarios = []
    success_scenarios = []
    
    # 逐个测试
    for i, scenario in enumerate(test_scenarios, 1):
        scenario_id = scenario.get("scenario_id")
        anomaly_component = scenario.get("anomaly_component")
        
        print(f"\n[{i}/{len(test_scenarios)}] 测试场景: {scenario_id}")
        print(f"  异常组件: {anomaly_component}")
        
        # 发送请求
        result = send_case_construction_request(
            url=url,
            scenario_id=scenario_id,
            components=components,
            timeout=timeout,
            verbose=verbose
        )
        
        # 记录结果
        if result["success"]:
            success_count += 1
            success_scenarios.append({
                "scenario_id": scenario_id,
                "anomaly_component": anomaly_component
            })
            print(f"  ✅ 成功")
        else:
            failed_count += 1
            failed_scenarios.append({
                "scenario_id": scenario_id,
                "anomaly_component": anomaly_component,
                "error_type": result.get("error_type", "Unknown"),
                "error": result.get("error", "Unknown error"),
                "error_detail": result.get("error_detail")
            })
            print(f"  ❌ 失败: {result.get('error_type', 'Unknown')}")
            if verbose and "error_detail" in result:
                print(f"  错误详情: {result['error_detail']}")
    
    # 打印统计摘要
    print("\n" + "=" * 80)
    print(f"📊 测试完成统计:")
    print(f"  总场景数: {len(test_scenarios)}")
    print(f"  ✅ 成功: {success_count}")
    print(f"  ❌ 失败: {failed_count}")
    print(f"  成功率: {success_count / len(test_scenarios) * 100:.1f}%")
    
    # 打印失败详情
    if failed_scenarios:
        print(f"\n❌ 失败的场景列表 ({failed_count} 个):")
        for i, failed in enumerate(failed_scenarios, 1):
            print(f"  {i}. {failed['scenario_id']}")
            print(f"     异常组件: {failed['anomaly_component']}")
            print(f"     错误类型: {failed['error_type']}")
            if failed.get('error_detail'):
                error_detail = failed['error_detail']
                if isinstance(error_detail, dict):
                    error_msg = error_detail.get('error', str(error_detail))
                else:
                    error_msg = str(error_detail)
                print(f"     错误信息: {error_msg}")
    
    return {
        "total": len(test_scenarios),
        "success": success_count,
        "failed": failed_count,
        "success_rate": success_count / len(test_scenarios) * 100 if test_scenarios else 0,
        "failed_scenarios": failed_scenarios,
        "success_scenarios": success_scenarios
    }


def main():
    """主函数"""
    parser = argparse.ArgumentParser(
        description="发送案例构建请求",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
示例:
  # 使用默认参数（单个场景）
  python scripts/send_case_construction_request.py
  
  # 批量测试所有 test 场景
  python scripts/send_case_construction_request.py --batch-test --samples-json data/envs/aiops-22/samples.json
  
  # 自定义 URL 和参数
  python scripts/send_case_construction_request.py \\
      --url http://133.133.134.61:5000/api/case_construction \\
      --scenario-id checkoutservice2-0_1652075078 \\
      --components checkoutservice node
  
  # 显示详细输出
  python scripts/send_case_construction_request.py --verbose
        """
    )
    
    parser.add_argument(
        "--url",
        type=str,
        default="http://122.112.193.220:15001/api/case_construction",
        help="API 端点 URL（默认: http://122.112.193.220:15001/api/case_construction）"
    )
    
    parser.add_argument(
        "--scenario-id",
        type=str,
        default="adservice_1651909424",
        help="场景 ID（单场景模式）"
    )
    
    parser.add_argument(
        "--components",
        type=str,
        nargs="+",
        default=["productcatalogservice", 'node-5', "recommendationservice"],
        help="组件列表（默认: cartservice）"
    )
    
    parser.add_argument(
        "--timeout",
        type=int,
        default=30,
        help="请求超时时间（秒，默认: 30）"
    )
    
    parser.add_argument(
        "--verbose", "-v",
        action="store_true",
        help="显示详细输出"
    )
    
    parser.add_argument(
        "--batch-test",
        action="store_true",
        help="批量测试所有 test 场景"
    )
    
    parser.add_argument(
        "--samples-json",
        type=str,
        default="data/envs/aiops-22/samples.json",
        help="samples.json 文件路径（批量测试模式，默认: data/envs/aiops-22/samples.json）"
    )
    
    args = parser.parse_args()
    
    # 批量测试模式
    if args.batch_test:
        print(f"🔍 批量测试模式")
        print(f"   samples.json: {args.samples_json}")
        print(f"   API URL: {args.url}")
        print(f"   默认组件: {args.components}")
        
        stats = batch_test_scenarios(
            samples_json_path=args.samples_json,
            url=args.url,
            components=args.components,
            timeout=args.timeout,
            verbose=args.verbose
        )
        
        # 保存失败场景列表到文件
        if stats.get("failed_scenarios"):
            output_file = "failed_scenarios.json"
            with open(output_file, 'w', encoding='utf-8') as f:
                json.dump(stats["failed_scenarios"], f, indent=2, ensure_ascii=False)
            print(f"\n💾 失败场景详情已保存到: {output_file}")
        
        return 0 if stats.get("failed", 0) == 0 else 1
    
    # 单场景模式
    else:
        # 发送请求
        result = send_case_construction_request(
            url=args.url,
            scenario_id=args.scenario_id,
            components=args.components,
            timeout=args.timeout,
            verbose=args.verbose
        )
        
        # 输出结果
        if result["success"]:
            print("\n✅ 请求成功")
            print(f"状态码: {result['status_code']}")
            print(f"响应数据:")
            print(json.dumps(result["data"], indent=2, ensure_ascii=False))
            return 0
        else:
            print(f"\n❌ 请求失败")
            print(f"错误类型: {result.get('error_type', 'Unknown')}")
            print(f"错误信息: {result.get('error', 'Unknown error')}")
            if "status_code" in result:
                print(f"HTTP 状态码: {result['status_code']}")
            if "error_detail" in result:
                print(f"错误详情: {json.dumps(result['error_detail'], indent=2, ensure_ascii=False)}")
            return 1


if __name__ == "__main__":
    exit_code = main()
    sys.exit(exit_code)